#include "Player.h"
#include "../../../SGD_Wrappers/CSGD_DirectInput.h"
#include "../../../SGD_Wrappers/CSGD_TextureManager.h"
#include "../../../SGD_Wrappers/CSGD_EventSystem.h"
#include "../../../SGD_Wrappers/CSGD_Direct3D.h"
#include "../../../SGD_Wrappers/CSGD_MessageSystem.h"
#include "../../../SGD_Wrappers/Message.h"
#include "../Gun/FireGun.h"
#include "../Gun/IceGun.h"
#include "../Gun/WindGun.h"
#include "../Gun/LightningGun.h"
#include "../../../source/DestroyEntityMessage.h"
#include "../../../SGD_Wrappers/SGD_String.h"
#include "../../../SGD_Wrappers/SGD_Math.h"
#include <fstream>
#include <iostream>
#include "../../Tiles/Tile.h"
using namespace std;
#include "../../Animations/AnimationInfo.h"

CPlayer::CPlayer(void)
{
	this->m_eType = ENTITY_PLAYER;

	m_pTM = CSGD_TextureManager::GetInstance();
	m_pDI = CSGD_DirectInput::GetInstance();
	m_pES = CSGD_EventSystem::GetInstance();
	m_pD3D = CSGD_Direct3D::GetInstance();

	m_pES->RegisterClient("DRAIN_ENERGY", this);
	m_pES->RegisterClient("PLAYER_ATTACK",this);
	m_pES->RegisterClient("FIRE",this);
	m_pES->RegisterClient("SCORE_INCREASE",this);
	m_pES->RegisterClient("WALL",this);
	m_pES->RegisterClient("HEAL",this);
	m_pES->RegisterClient("ICE",this);
	m_pES->RegisterClient("TAR",this);
	m_pES->RegisterClient("PICK_UP",this);
	m_pES->RegisterClient("GROUND",this);
	m_pES->RegisterClient("BOTTOMLESS",this);
	m_pES->RegisterClient("done_kick",this);



	m_pgFireGun = new CFireGun(this);
	m_pgIceGun = new CIceGun;
	m_pgWindGun = new CWindGun;
	m_pgLiGun = new CLightningGun;
	m_bOnTar = false;
	m_bOnIce = false;
	m_pgLiGun->SetOwner( this );

	this->m_fDashCooldown = 0.0f;
	this->m_fShieldCoolDown = 0.0f;
	this->m_fShieldDuration = 0.0f;

	m_fTarDuration = 1.0f;
	m_bIsDashing = false; 
	m_nNumKeys = 0;
	m_nEnergy = 100.0f;
	m_nMaxEnergy = 100.0f;
	m_nEnergyRegenRate = 3.0f;
	SetHealth(100);
	SetMaxHealth(100);
	SetVelY(0);
	SetVelX(0);
	SetPosX(200);
	SetPosY(200);
	m_eCurrGun = GUN_FIRE;
	this->m_nPowerUp = 0;
	m_poMouseClick.x = 0;
	m_poMouseClick.y = 0;
	m_nEnemies = 1;
	m_nCurrLevel = 1;
	m_nCurrFloor = 1;
	m_cAnimationInfo = new CAnimationInfo();
	m_cAnimationInfo->SetAnimation("Stand",true);
	m_bShield = false;

}
void CPlayer::Init()
{
	this->m_fDashCooldown = 0.0f;
	this->m_fShieldCoolDown = 0.0f;
	this->m_fShieldDuration = 0.0f;

	m_bIsDashing = false; 
	m_nNumKeys = 0;
	m_nEnergy = 100.0f;
	m_nMaxEnergy = 100.0f;
	m_nEnergyRegenRate = 3.0f;
	SetHealth(100);
	SetMaxHealth(100);
	SetVelY(0);
	SetVelX(0);
	SetPosX(200);
	SetPosY(200);
	m_eCurrGun = GUN_FIRE;
	this->m_nPowerUp = 0;
	m_poMouseClick.x = 0;
	m_poMouseClick.y = 0;
	m_nEnemies = 1;
	m_nCurrLevel = 1;
	m_nCurrFloor = 1;
	m_bShield = false;
}
CPlayer::~CPlayer(void)
{
	delete m_pgFireGun;
	delete m_pgIceGun;
	delete m_pgWindGun;
	delete m_pgLiGun;
	delete m_cAnimationInfo;
}
void CPlayer::Update(float fElapsedTime)
{
	m_fElapsedTime = fElapsedTime;

	m_cAnimationInfo->Update(fElapsedTime);
	m_pgFireGun->Update(fElapsedTime);
	m_pgIceGun->Update(fElapsedTime);
	m_pgWindGun->Update(fElapsedTime);
	m_pgLiGun->Update(fElapsedTime);

	CPlayer::Input(fElapsedTime);
	CPlayer::Shoot(fElapsedTime);
	CPlayer::Dash(fElapsedTime);
	CPlayer::SwitchGun();

	m_vToMouse.fX = m_pDI->MouseGetPosX() - GetPosX();
	m_vToMouse.fY = m_pDI->MouseGetPosY() - GetPosY();

	tVector2D vOrientation = {0,-1};
	vOrientation = Vector2DRotate(vOrientation,this->GetRotation());
	float fAngle = AngleBetweenVectors(vOrientation,m_vToMouse);
	float fMaxRot = (SGD_PI)*fElapsedTime;
	if(fAngle > fMaxRot)
		fAngle = fMaxRot;

	if(Steering(vOrientation, m_vToMouse)<0)
	{
		fAngle= -fAngle;
	}
	
	this->SetRotation(this->GetRotation()-fAngle);


	m_fDashCooldown -= fElapsedTime;
	if(m_fDashCooldown <= 0.0f && m_bIsDashing)
	{
		SetVelX(0);
		SetVelY(0);
		m_bIsDashing = false;
	}
	m_fShieldCoolDown -= fElapsedTime;
	if(m_fShieldDuration < 0.0f)
		m_bShield = false;
	if(m_nEnergy < m_nMaxEnergy)
		m_nEnergy += m_nEnergyRegenRate*fElapsedTime;
	
	if(m_nEnergy > m_nMaxEnergy)
		m_nEnergy = m_nMaxEnergy;

	if(this->GetHealth() <= 0)
	{
		IMessage* i = new CDestroyEntityMessage( this );
		CSGD_MessageSystem::GetInstance()->SendMsg( i );
		i = nullptr;
	}

	m_fTarDuration -= fElapsedTime;
	if(m_fTarDuration <= 0.0f)
		m_bOnTar = false;

	
}

void CPlayer::Render()
{
	m_cAnimationInfo->Draw(GetPosX(),GetPosY(),GetRotation());
	m_pD3D->GetSprite()->Flush();
	RECT rHBar = {(long)0,(long)0,(long)Lerp((float)0,(float)200,(float)GetHealth()/(float)GetMaxHealth()),(long)50 };
	m_pD3D->DrawRect(rHBar,255,0,0);

	RECT rEBar = {250,0,(LONG)Lerp(250,600,(float)m_nEnergy/(float)m_nMaxEnergy),50 };
	m_pD3D->DrawRect(rEBar,255,255,0);
	if(m_bShield)
		m_pD3D->DrawRect(GetRect(),0,0,255);
	m_pD3D->DrawText(_T("Kills: "), 100,400,255,255,255);
	TOSTRINGSTREAM ToScreen;
	ToScreen << m_nEnemies;
	m_pD3D->DrawText(ToScreen.str().c_str(),180,400,255,255,255);
}

 void CPlayer::Shoot(float fElapsedTime)
{
	if(m_pDI->MouseButtonPressed(0))
	{
		if(m_eCurrGun == CPlayer::GUN_FIRE)
			this->m_pgFireGun->Shoot();
		else if(m_eCurrGun == CPlayer::GUN_ICE)
			this->m_pgIceGun->Shoot();
		else if(m_eCurrGun == CPlayer::GUN_LIGHTNING)
			this->m_pgLiGun->Shoot();
		else if(m_eCurrGun == CPlayer::GUN_WIND)
			this->m_pgWindGun->Shoot();
		
		m_cAnimationInfo->SetAnimation("Kick",false);

		GetCursorPos(&m_poMouseClick);
	}
}
void CPlayer::SwitchGun()
{
	if(m_pDI->KeyPressed(DIK_1))
		m_eCurrGun = GUN_FIRE;
	if(m_pDI->KeyPressed(DIK_2))
		m_eCurrGun = GUN_ICE;
	if(m_pDI->KeyPressed(DIK_3))
		m_eCurrGun = GUN_LIGHTNING;
	if(m_pDI->KeyPressed(DIK_4))
		m_eCurrGun = GUN_WIND;
}
void CPlayer::Heal(float nAmount)
{
	if(GetHealth() < GetMaxHealth())
		SetHealth(GetHealth()+nAmount);
}
bool CPlayer::CheckCollision(IEntity* pOther)
{
	return CEntity::CheckCollision(pOther);
}
void CPlayer::PickUp(int nType)
{
	if(nType == 0)
		this->m_nNumKeys++;
	else if(nType == 1)
		this->m_nPowerUp = 1;
}
void CPlayer::Dash(float fElapsedTime)
{
	if(m_pDI->KeyDown(DIK_SPACE))
	{
		if(this->m_fDashCooldown <= 0.0f)
		{
			this->m_bIsDashing = true;
			m_fDashCooldown = 2.0f;
		}
	}
}
void CPlayer::Input(float fElapsedTime)
{
	if(!m_bIsDashing)
	{
		if(m_pDI->KeyDown(DIK_W)) // Up
			SetVelY( GetVelY() - GetMoveSpeed() * fElapsedTime );
		if(m_pDI->KeyDown(DIK_S)) // Down
			SetVelY( GetVelY() + GetMoveSpeed() * fElapsedTime );
		if(m_pDI->KeyDown(DIK_A)) // Left
			SetVelX( GetVelX() - GetMoveSpeed() * fElapsedTime );
		if(m_pDI->KeyDown(DIK_D)) // Right
			SetVelX( GetVelX() + GetMoveSpeed() * fElapsedTime );

		if(m_pDI->KeyReleased(DIK_W)) // Up
			this->SetVelY(0);
		if(m_pDI->KeyReleased(DIK_S)) // Down
			this->SetVelY(0);
		if(m_pDI->KeyReleased(DIK_A)) // Left
			this->SetVelX(0);
		if(m_pDI->KeyReleased(DIK_D)) // Right
			this->SetVelX(0);
	}

	if(!m_bIsDashing && !m_bOnTar)
	{
		SetPrevPosX( GetPosX() );
		SetPrevPosY( GetPosY() );
		this->SetPosY(this->GetPosY()+this->GetVelY()*fElapsedTime);
		this->SetPosX(this->GetPosX()+this->GetVelX()*fElapsedTime);
	}
	else if(m_bIsDashing || m_bOnIce)
	{
		SetPrevPosX( GetPosX() );
		SetPrevPosY( GetPosY() );
		this->SetPosY(this->GetPosY()+this->GetVelY()*fElapsedTime*2);
		this->SetPosX(this->GetPosX()+this->GetVelX()*fElapsedTime*2);
	}
	else if(m_bOnTar)
	{
		SetPrevPosX( GetPosX() );
		SetPrevPosY( GetPosY() );
		this->SetPosY(this->GetPosY()+this->GetVelY()*fElapsedTime*0.1f);
		this->SetPosX(this->GetPosX()+this->GetVelX()*fElapsedTime*0.1f);
	}
	
	if(m_pDI->KeyDown(DIK_LSHIFT))
	{
		if(m_nPowerUp == 1)
		{
			m_bShield = true;
			m_fShieldDuration = 50.0f;
		}
	}
}
void CPlayer::TakeDamage(float nDamage)
{
	if(this->m_fShieldDuration > 0.0f)
		m_fShieldDuration -= nDamage;
	else
		CCharacter::TakeDamage((int)nDamage);
}

RECT CPlayer::GetRect()
{
	return CEntity::GetRect();
}

void CPlayer::AddRef()
{
	CEntity::AddRef();
}

void CPlayer::HandleEvent(CEvent* pEvent)
{
	if(this == pEvent->GetDestination())
	{
		if(pEvent->GetEventID() == "PLAYER_ATTACK")
		{			
			int temp = (int)pEvent->GetParam();
			this->TakeDamage((float)temp);
		}

		if(pEvent->GetEventID() == "FIRE")
		{			
			int temp = (int)pEvent->GetParam();
			this->TakeDamage((float)temp*m_fElapsedTime);
		}

		if(pEvent->GetEventID() == "HEAL")
		{
			int temp = (int)pEvent->GetParam();
			this->Heal((float)temp*m_fElapsedTime);
		}
		if(pEvent->GetEventID() == "ICE")
		{
			m_bIsDashing = true;
			m_fDashCooldown = 0.1f;
		}
		if(pEvent->GetEventID() == "WALL")
		{
			//CTile* temptile = reinterpret_cast<CTile*>(pEvent->GetSender());
			//float tileX = temptile->GetWorldPosX();
			//float tileY = temptile->GetImagePosY();

			//vOrientation.fX = 0.0f;
			//vOrientation.fY = -1.0f;
			//vOrientation = Vector2DRotate(vOrientation,this->GetRotation());
			//SetVelX( vOrientation.fX * tempMoveSpeed);
			//SetVelY( vOrientation.fX * tempMoveSpeed);
			//CEntity::SetVelX( (GetPosX() - tileX + GetWidth()/2) * 0.03f );
			//CEntity::SetVelY( (GetPosY() - tileY + GetWidth()/2) * 0.03f );

			SetPosX( GetPrevPosX() );
			SetPosY( GetPrevPosY() );
		}
		

		if(pEvent->GetEventID() == "BOTTOMLESS")
		{
			SetHealth(0);
		}


		if(pEvent->GetEventID() == "done_kick")
		{
			m_cAnimationInfo->SetAnimation("Stand",true);
		}
	}
	if(pEvent->GetEventID() == "PICK_UP")
	{
		PickUp((int)pEvent->GetParam());
	}
	if(pEvent->GetEventID() == "DRAIN_ENERGY")
	{
		m_nEnergy-=(int)pEvent->GetParam();
	}

	if(pEvent->GetEventID() == "SCORE_INCREASE")
	{
		m_nEnemies++;
	}

	if(pEvent->GetEventID() == "TAR" && pEvent->GetDestination() == this)
	{
		m_bOnTar = true;
		m_fTarDuration = 0.1f;
	}
}

void CPlayer::Load(int nSave)
{
	ifstream fin;
	if(nSave == 1)
	{
		fin.open("Save1.txt",ios_base::in);

		if(fin.good())
			{
				fin >> m_nCurrLevel;
				fin.ignore(INT_MAX, '\n');
				fin >> m_nCurrFloor;
				fin.ignore(INT_MAX, '\n');
				fin >> m_nEnemies;
			}

		fin.close();
	}
	else if(nSave == 2)
	{
		fin.open("Save2.txt",ios_base::in);

		if(fin.good())
			{
				fin >> m_nCurrLevel;
				fin.ignore(INT_MAX, '\n');
				fin >> m_nCurrFloor;
				fin.ignore(INT_MAX, '\n');
				fin >> m_nEnemies;
			}

		fin.close();
	}
	else if(nSave == 3)
	{
		fin.open("Save3.txt",ios_base::in);

		if(fin.good())
			{
				fin >> m_nCurrLevel;
				fin.ignore(INT_MAX, '\n');
				fin >> m_nCurrFloor;
				fin.ignore(INT_MAX, '\n');
				fin >> m_nEnemies;
			}

		fin.close();
	}
}
void CPlayer::Save(int nSave)
{
	if(nSave == 1)
	{
		ofstream fout("Save1.txt", ios_base::out);
		if(fout.is_open())
		{
			if(fout.good())
			{
				fout << m_nCurrLevel << "\n" << m_nCurrFloor << "\n" << m_nEnemies;
			}
			fout.close();
		}
	}
	else if(nSave == 2)
	{
		ofstream fout("Save2.txt", ios_base::out);
		if(fout.is_open())
		{
			if(fout.good())
			{
				fout << m_nCurrLevel << "\n" << m_nCurrFloor << "\n" << m_nEnemies;
			}
			fout.close();
		}
	}
	else if(nSave == 3)
	{
		ofstream fout("Save3.txt", ios_base::out);
		if(fout.is_open())
		{
			if(fout.good())
			{
				fout << m_nCurrLevel << "\n" << m_nCurrFloor << "\n" << m_nEnemies;
			}
			fout.close();
		}
	}
}
